<template>
  <div id="app">
    <div class="toolbar">
      <div class="commonds"></div>
      <div class="options">
        <div id="options">
            <label class="item">
              编译:
              <select v-model="engine">
                <option v-for="item in engineList" :key="item" :selected="item === engine">{{item}}</option>
              </select>
            </label>

            <label class="item">
              输出:
              <select v-model="format">
                <option v-for="item in formatList" :key="item" :selected="item === format">{{item}}</option>
              </select>
            </label>

            <span class="block item" @click="toggoleShowOutput" title="预览">
              <i v-if="showOutput" class="icon iconfont icon-eye"></i>
              <i v-else class="icon iconfont icon-eye-close"></i>
            </span>
          </div>
      </div>
    </div>
    <div class="main">
      <ace-editor v-model="content" @change="contentChange" :width="editorWidth + 'px'" height="100%"/>
      <div v-show="showOutput" class="gutter" @mousedown="gutterMousedown"></div>
      <div v-show="showOutput" ref="output" class="output" :style="{width: viewWidth + 'px'}">
        <div class="text" v-if="format != 'png-image-element'" v-html="result" :style="{textAlign: format == 'svg' ? 'center' : ''}"></div>
        <i @click="saveOutput" class="icon iconfont icon-save" title="保存"></i>
      </div>
    </div>
  </div>
</template>

<script>
import AceEditor from './components/AceEditor'
import Viz from 'viz.js'
import fs from 'fs'

const { app, dialog } = require('electron').remote

export default {
  name: 'App',
  data () {
    return {
      showOutput: true,
      editorWidth: 500,
      content: '',
      result: null,
      // 输出格式
      format: 'svg',
      // 编译引擎
      engine: 'dot',
      formatList: ['svg', 'png-image-element', 'json', 'xdot', 'plain'],
      engineList: ['circo', 'dot', 'fdp', 'neato', 'osage', 'twopi']
    }
  },
  created () {
    this.editorWidth = window.innerWidth * 0.4
    window.onresize = () => {
      this.editorWidth = Math.min(window.innerWidth * 0.4, 500)
    }
  },
  computed: {
    viewWidth () {
      return window.innerWidth - this.editorWidth - 7
    }
  },
  components: {
    AceEditor
  },
  methods: {
    gutterMousedown (e) {
      // 拖拽分隔栏，
      // if (e.shiftKey) {
      const _self = this
      const el = e.target
      document.onmousemove = function (e) {
        _self.editorWidth += e.clientX - el.offsetLeft
        if (_self.editorWidth > (window.innerWidth * 0.95)) {
          _self.showOutput = false
        } else {
          _self.showOutput = true
        }
      }
      document.onmouseup = function (e) {
        document.onmousemove = null
        document.onmouseup = null
      }
    },
    contentChange (content) {
      this.generateVizResult()
    },
    generateVizResult () {
      if (!this.showOutput) {
        return
      }
      const imgEl = document.querySelector('.output img')
      if (imgEl) {
        this.$refs.output.removeChild(imgEl)
      }
      try {
        this.result = Viz(this.content, {
          format: this.format,
          engine: this.engine,
          scale: 2
        })
        if (this.format === 'png-image-element') {
          // 图片对象
          this.$refs.output.appendChild(this.result)
        }
      } catch (error) {
      }
    },
    toggoleShowOutput () {
      this.showOutput = !this.showOutput
      if (this.showOutput) {
        this.editorWidth = Math.min(window.innerWidth * 0.4, 500)
        this.generateVizResult()
      } else {
        this.editorWidth = window.innerWidth
      }
    },
    saveOutput () {
      // 默认保存文件夹 桌面
      let filters = []
      if (this.format === 'svg') {
        filters = [{name: 'Svg', extensions: ['svg']}]
      } else if (this.format === 'png-image-element') {
        filters = [{name: 'Images', extensions: ['png']}]
      } else if (this.format === 'json') {
        filters = [{name: 'Json', extensions: ['json']}]
      } else {
        filters = [{name: 'Text', extensions: ['text']}]
      }
      dialog.showSaveDialog({
        title: '保存文件',
        defaultPath: app.getPath('desktop'),
        filters
      }, (filepath) => {
        let stringBuffer = this.result
        if (this.format === 'png-image-element') {
          const base64Data = this.result.src.replace(/^data:image\/\w+;base64,/, '')
          stringBuffer = Buffer.from(base64Data, 'base64')
        }
        fs.writeFile(filepath, stringBuffer, (e, data) => {
          alert('保存成功！！！')
        })
      })
    }
  },
  watch: {
    engine () {
      this.generateVizResult()
    },
    format () {
      this.generateVizResult()
    }
  }
}
</script>

<style>
* {
  padding: 0;
  margin: 0;
}
#app {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
}
.toolbar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  width: 100%;
  height: 50px;
  line-height: 50px;
  box-shadow: 0 0 10px #c4c4c4;
  z-index: 100;
  background: #fff;
  display: flex;
  justify-content: space-between;
}
.main {
  padding-top: 50px;
  height: calc(100% - 50px);
  display: flex;
  overflow: hidden;
}
.options .item {
  margin-right: 20px;
}
.options .block i {
  font-size: 21px;
  cursor: pointer;
  color: #444;
}
.gutter {
  width: 7px;
  min-width: 7px;
  height: 100%;
  background-image: url();
  background-color: #b1b1b1;
  background-repeat: no-repeat;
  background-position: 50%;
  cursor: ew-resize;
}
.output {
  flex: 1 1 auto;
  position: relative;
  overflow: auto;
}
.output img {
  display: block;
  margin: 0 auto;
  margin-top: 20px;
}
.output .text {
  font-size: 14px;
  font-family: monaco, courier, monospace;
  white-space: pre;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
}
.output .icon-save {
  position: absolute;
  top: 30px;
  right: 30px;
  color: #444;
  font-size: 40px;
  cursor: pointer;
}
</style>
